package runner.SAPSO_VM;

import org.cloudbus.cloudsim.Host;
import org.cloudbus.cloudsim.Log;
import org.cloudbus.cloudsim.Vm;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.power.PowerHost;
import org.cloudbus.cloudsim.power.PowerVmAllocationPolicyAbstract;

import java.util.*;

public class PowerVmAllocationPolicySAPSO extends PowerVmAllocationPolicyAbstract {

    private static double[] mapping = null;
    private static SAPSO SAPSOSchedularInstance;
//    private List<Vm> vmList;
//    private List<PowerHost> hostList;

    public PowerVmAllocationPolicySAPSO(List<? extends Vm> vmList, List<? extends Host> hostList) {
        super(hostList);
//        this.vmList = (List<Vm>) vmList;
//        this.hostList = (List<PowerHost>) hostList;
        SAPSOSchedularInstance = new SAPSO((List<Vm>) vmList, (List<PowerHost>) hostList);
        mapping = SAPSOSchedularInstance.run();
//        placeVmByMapping(mapping, vmList, (List<PowerHost>) hostList);
    }

    private List<Map<String, Object>> placeVmByMapping(
            double[] bestPosition, List<? extends Vm> vmlist, List<PowerHost> hosts) {

        int index = 0;
        for (Vm vm : vmlist) {  // 遍历待放置的虚拟机列表
            PowerHost host = hosts.get((int) bestPosition[index]); // 获取当前vm放置的主机
            if (!host.isSuitableForVm(vm)) {
                PowerHost allocatedHost = findHostForVm(vm, hosts);
                if (allocatedHost != null) host = allocatedHost;
            }
            try {
                host.vmCreate(vm);
                Log.printConcatLine("VM #", vm.getId(), " allocated to host #", host.getId());
//                Map<String, Object> map = new HashMap<>();
//                map.put("vm", vm);
//                map.put("host", host);
//                migrationMap.add(map);
            } catch (Exception e) {
                Log.formatLine(
                        "%.2f: Creation of VM #" + vm.getId() + " on the host #" + host.getId() + " failed\n",
                        CloudSim.clock());
            }
            index ++;
        }

        return null;
    }
    public PowerHost findHostForVm (Vm vm, List<PowerHost> hosts) {
        for (PowerHost h : hosts) {
            if (h.isSuitableForVm(vm)) {
                return h;
            }
        }
        return null;
    }

    @Override
    public boolean allocateHostForVm(Vm vm, Host host) {
        if (host.vmCreate(vm)) {
            getVmTable().put(vm.getUid(), host);
            Log.formatLine("%.2f: VM #" + vm.getId() + " has been allocated to the host #" + host.getId(), CloudSim.clock());
            return true;
        }
        Log.formatLine("%.2f: Creation of VM #" + vm.getId() + " on the host #" + host.getId() + " failed\n", CloudSim.clock());
        return false;
    }

    public PowerHost findHostForVm (Vm vm) {
        List<PowerHost> hostList = this.getHostList();
        int vmId = vm.getId();
        PowerHost host = null;
        for (int i = 0, mappingLength = mapping.length; i < mappingLength; i++) {
            double v = mapping[i];
            host = hostList.get((int) v);

            if (host.isSuitableForVm(vm)) {
                break;
            } else {
                if (i == mappingLength -1) {
                    host = super.findHostForVm(vm);
                }
            }
        }



//        PowerHost host = hostList.get((int) mapping[vmId]);
//        System.out.println("VM #" + vmId +" should been allocated to the host #" + host.getId());
//        if (!host.isSuitableForVm(vm)) {
//            for (double m : mapping) {
//                PowerHost newHost = hostList.get((int) m);
//                if (host.isSuitableForVm(vm)) {
//                    host = newHost;
//                    break;
//                }
//            }
//
//        }

        return host;
    }


    @Override
    public List<Map<String, Object>> optimizeAllocation(List<? extends Vm> vmList) {
        return null;
    }


}
